<div class="tmd-doc">
<h1 class="tmd-header-1">
Go Type System Overview
</h1>
<p></p>
<div class="tmd-usual">
This article will introduce all kinds of types in Go and the concepts regarding Go type system. Without knowing these fundamental concepts, it is hard to have a thorough understanding of Go.
</div>
<p></p>
<h3 class="tmd-header-3">
Concept: Basic Types
</h3>
<p></p>
<div class="tmd-usual">
Built-in basic types in Go have been also introduced in <a href="basic-types-and-value-literals.html">built-in basic types and basic value literals</a>. For completeness of the current article, these built-in basic types are re-listed here.
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
Built-in string type: <code class="tmd-code-span">string</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Built-in boolean type: <code class="tmd-code-span">bool</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
Built-in numeric types:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">int8</code>, <code class="tmd-code-span">uint8</code> (<code class="tmd-code-span">byte</code>), <code class="tmd-code-span">int16</code>, <code class="tmd-code-span">uint16</code>, <code class="tmd-code-span">int32</code> (<code class="tmd-code-span">rune</code>), <code class="tmd-code-span">uint32</code>, <code class="tmd-code-span">int64</code>, <code class="tmd-code-span">uint64</code>, <code class="tmd-code-span">int</code>, <code class="tmd-code-span">uint</code>, <code class="tmd-code-span">uintptr</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">float32</code>, <code class="tmd-code-span">float64</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">complex64</code>, <code class="tmd-code-span">complex128</code>.
</div>
</li>
</ul>
</li>
</ul>
<p></p>
<p></p>
<div class="tmd-usual">
Note, <code class="tmd-code-span">byte</code> is a built-in alias of <code class="tmd-code-span">uint8</code>, and <code class="tmd-code-span">rune</code> is a built-in alias of <code class="tmd-code-span">int32</code>. We can also declare custom type aliases (see below).
</div>
<p></p>
<div class="tmd-usual">
Except <a href="string.html">string types</a>, Go 101 article series will not try to explain more on other basic types.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
The 17 built-in basic types are predeclared types.
</div>
<p></p>
<h3 class="tmd-header-3">
Concept: Composite Types
</h3>
<p></p>
<div class="tmd-usual">
Go supports the following composite types:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="pointer.html">pointer types</a> - C pointer alike.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="struct.html">struct types</a> - C struct alike.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="function.html">function types</a> - functions are first-class types in Go.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="container.html">container types</a>:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
array types - fixed-length container types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
slice type - dynamic-length and dynamic-capacity container types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
map types - maps are associative arrays (or dictionaries). The standard Go compiler implements maps as hashtables.
</div>
</li>
</ul>
<p></p>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="channel.html">channel types</a> - channels are used to synchronize data among goroutines (the green threads in Go).
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="interface.html">interface types</a> - interfaces play a key role in reflection and polymorphism.
</div>
</li>
</ul>
<p></p>
<p></p>
<div class="tmd-usual">
Unnamed composite types may be denoted by their respective type literals. Following are some literal representation examples of all kinds of unnamed composite types (name and unnamed types will be explained below).
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">// Assume T is an arbitrary type and Tkey is
// a type supporting comparison (== and !=).

*T         // a pointer type
[5]T       // an array type
[]T        // a slice type
map[Tkey]T // a map type

// a struct type
struct {
	name string
	age  int
}

// a function type
func(int) (bool, string)

// an interface type
interface {
	Method0(string) int
	Method1() (int, bool)
}

// some channel types
chan T
chan&lt;- T
&lt;-chan T
</code></pre>
<p></p>
<div class="tmd-usual">
<a href="#types-not-support-comparison">Comparable and incomparable types</a> will be explained below.
</div>
<p></p>
<p></p>
<h3 id="type-kinds" class="tmd-header-3">
Fact: Kinds of Types
</h3>
<p></p>
<div class="tmd-usual">
Each of the above mentioned basic and composite types corresponds to one kind of types. Besides these kinds, the unsafe pointer types introduced in the <a href="https://golang.org/pkg/unsafe"><code class="tmd-code-span">unsafe</code> standard package</a> also belong to one kind of types in Go. So, up to now (Go 1.25), Go has 26 kinds of types.
</div>
<p></p>
<p></p>
<h3 id="type-definition" class="tmd-header-3">
Syntax: Type Definitions
</h3>
<p></p>
<div class="tmd-usual">
<span class="tmd-italic">(<span class="tmd-bold">Type definition</span>, or type definition declaration, initially called <span class="tmd-bold">type declaration</span>, was the only type declaration way before Go 1.9. Since Go 1.9, type definition has become one of two forms of type declarations. The new form is called <span class="tmd-bold">type alias declaration</span>, which will be introduced in a section below.)</span>
</div>
<p></p>
<div class="tmd-usual">
In Go, we can define new types by using the following form. In the syntax, <code class="tmd-code-span">type</code> is a keyword.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">// Define a solo new type.
type NewTypeName SourceType

// Define multiple new types together.
type (
	NewTypeName1 SourceType1
	NewTypeName2 SourceType2
)
</code></pre>
<p></p>
<div class="tmd-usual">
New type names must be identifiers. But please note that, type names declared at package level can't be <a href="packages-and-imports.html#init"><code class="tmd-code-span">init</code></a>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
The second type declaration in the above example includes two type specifications. If a type declaration contains more than one type specification, the type specifications must be enclosed within a pair of <code class="tmd-code-span">()</code>.
</div>
<p></p>
<div class="tmd-usual">
Note,
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
a new defined type and its respective source type in type definitions are two distinct types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
two types defined in two type definitions are always two distinct types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the new defined type and the source type will share the same underlying type (see below for the definition of underlying types), and their values can be converted to each other.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
types can be defined within function bodies.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Some type definition examples:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">// The following new defined and source types are all
// basic types. The source types are all predeclared.
type (
	MyInt int
	Age   int
	Text  string
)

// The following new defined and source types are all
// composite types. The source types are all unnamed.
type IntPtr *int
type Book struct{author, title string; pages int}
type Convert func(in0 int, in1 bool)(out0 int, out1 string)
type StringArray [5]string
type StringSlice []string

func f() {
	// The names of the three defined types
	// can be only used within the function.
	type PersonAge map[string]int
	type MessageQueue chan string
	type Reader interface{Read([]byte) int}
}
</code></pre>
<p></p>
<div class="tmd-usual">
Please note that, from Go 1.9 to Go 1.17, the Go specification ever thought predeclared built-in types are defined types. But since Go 1.18, the Go specification clarifies that predeclared built-in types are not defined types.
</div>
<p></p>
<h3 id="generic-type" class="tmd-header-3">
Concept: Custom Generic Types and Instantiated Types
</h3>
<p></p>
<div class="tmd-usual">
Since Go 1.18, Go has supported custom generic types (and functions). A generic type must be instantiated to be used as value types.
</div>
<p></p>
<div class="tmd-usual">
A generic type is a defined type and its instantiated types are named types (named types are explained in the next section).
</div>
<p></p>
<div class="tmd-usual">
The other two important concepts in custom generics are constraints and type parameters.
</div>
<p></p>
<div class="tmd-usual">
This book doesn't talk about custom generics in detail. Please read the <a href="https://go101.org/generics/101.html">Go Generics 101</a> book on how to declare and use generic types and functions.
</div>
<p></p>
<p></p>
<h3 id="named-type" class="tmd-header-3">
Concept: Named Types vs. Unnamed Types
</h3>
<p></p>
<div class="tmd-usual">
Before Go 1.9, the terminology <span class="tmd-bold">named type</span> is defined accurately in Go specification. A named type was defined as a type that is represented by an identifier. Along with the custom type alias feature introduced in Go 1.9 (see the next section), the <span class="tmd-bold">named type</span> terminology was ever removed from Go specification and it was replaced by the <span class="tmd-bold">defined type</span> terminology. Since Go 1.18, along with the introduction of custom generics, the <span class="tmd-bold">named type</span> terminology has been added back to Go specification.
</div>
<p></p>
<div class="tmd-usual">
A named type may be
</div>
<p></p>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
a predeclared type (not including <a href="#type-alias">type alias</a>);
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
a defined (non-custom-generic) type;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
an instantiated type (of a generic type);
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
a type parameter type (used in custom generics).
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Other value types are called unnamed types. An unnamed type must be a composite type (not vice versa).
</div>
<p></p>
<p></p>
<h3 id="type-alias" class="tmd-header-3">
Syntax: Type Alias Declarations
</h3>
<p></p>
<p></p>
<div class="tmd-usual">
Since Go 1.9, we can declare custom type aliases by using the following syntax. The syntax of alias declaration is much like type definition, but please note there is a <code class="tmd-code-span">=</code> in each type alias specification.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">type (
	Name = string
	Age  = int
)

type table = map[string]int
type Table = map[Name]Age
</code></pre>
<p></p>
<div class="tmd-usual">
Type alias names must be identifiers. Like type definitions, type aliases can also be declared within function bodies.
</div>
<p></p>
<div class="tmd-usual">
A type name (or literal) and its aliases all denote an identical type. By the above declarations, <code class="tmd-code-span">Name</code> is an alias of <code class="tmd-code-span">string</code>, so both denote the same type. The same applies to the other three pairs of type notations (either names or literals):
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">Age</code> and <code class="tmd-code-span">int</code>
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">table</code> and <code class="tmd-code-span">map[string]int</code>
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<code class="tmd-code-span">Table</code> and <code class="tmd-code-span">map[Name]Age</code>
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
In fact, the literals <code class="tmd-code-span">map[string]int</code> and <code class="tmd-code-span">map[Name]Age</code> also both denote the same type. So, similarly, aliases <code class="tmd-code-span">table</code> and <code class="tmd-code-span">Table</code> also denote the same type.
</div>
<p></p>
<div class="tmd-usual">
Note, although a type alias always has a name, it might denote an unnamed type. For example, the <code class="tmd-code-span">table</code> and <code class="tmd-code-span">Table</code> aliases both denote the same unnamed type <code class="tmd-code-span">map[string]int</code>.
</div>
<p></p>
<h3 id="underlying-type" class="tmd-header-3">
Concept: Underlying Types
</h3>
<p></p>
<div class="tmd-usual">
In Go, each type has an underlying type. Rules:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
for built-in types, the respective underlying types are themselves.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
for the <code class="tmd-code-span">Pointer</code> type defined in the <code class="tmd-code-span">unsafe</code> standard code package, its underlying type is itself (at least we can think so. In fact, the underlying type of the <code class="tmd-code-span">unsafe.Pointer</code> type is not well documented. We can also think the underlying type is <code class="tmd-code-span">*T</code>, where <code class="tmd-code-span">T</code> represents an arbitrary type). <code class="tmd-code-span">unsafe.Pointer</code> is also viewed as a built-in type.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the underlying type of an unnamed type, which must be a composite type, is itself.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
in a type declaration, the newly declared type and the source type have the same underlying type.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Examples:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">// The underlying types of the following ones are both int.
type (
	MyInt int
	Age   MyInt
)

// The following new types have different underlying types.
type (
	IntSlice   []int   // underlying type is []int
	MyIntSlice []MyInt // underlying type is []MyInt
	AgeSlice   []Age   // underlying type is []Age
)

// The underlying types of []Age, Ages, and AgeSlice
// are all the unnamed type []Age.
type Ages AgeSlice
</code></pre>
<p></p>
<div class="tmd-usual">
How can an underlying type be traced given a user declared type? The rule is, when a built-in basic type or an unnamed type is met, the tracing should be stopped. Take the type declarations shown above as examples, let's trace their underlying types.
</div>
<p></p>
<div class="tmd-callout">
<div class="tmd-callout-content">
<div class="tmd-usual">
<code class="tmd-mono-font">MyInt → int<br/>Age → MyInt → int<br/>IntSlice → []int<br/>MyIntSlice → []MyInt <span class="tmd-dimmed">→ <span class="tmd-deleted">[]int</span></span><br/>AgeSlice → []Age <span class="tmd-dimmed">→ <span class="tmd-deleted">[]MyInt</span> → <span class="tmd-deleted">[]int</span></span><br/>Ages → AgeSlice → []Age <span class="tmd-dimmed">→ <span class="tmd-deleted">[]MyInt</span> → <span class="tmd-deleted">[]int</span></span></code>
</div>
</div>
</div>
<p></p>
<div class="tmd-usual">
In Go,
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
types whose underlying types are <code class="tmd-code-span">bool</code> are called <span class="tmd-bold">boolean types</span>;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
types whose underlying types are any of the built-in integer types are called <span class="tmd-bold">integer types</span>;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
types whose underlying types are either <code class="tmd-code-span">float32</code> or <code class="tmd-code-span">float64</code> are called <span class="tmd-bold">floating-point types</span>;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
types whose underlying types are either <code class="tmd-code-span">complex64</code> or <code class="tmd-code-span">complex128</code> are called <span class="tmd-bold">complex types</span>;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
integer, floating-point and complex types are also called <span class="tmd-bold">numeric types</span>;
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
types whose underlying types are <code class="tmd-code-span">string</code> are called <span class="tmd-bold">string types</span>.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
The concept of underlying type plays an important role in <a href="value-conversions-assignments-and-comparisons.html">value conversions, assignments and comparisons in Go</a>.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Concept: Values
</h3>
<p></p>
<div class="tmd-usual">
An instance of a type is called a 'value' of the type. Values of the same type share some common properties. A type may have many values. One of them is the zero value of the type.
</div>
<p></p>
<div class="tmd-usual">
Each type has a zero value, which can be viewed as the default value of the type. The predeclared <code class="tmd-code-span">nil</code> identifier can used to represent zero values of slices, maps, functions, channels, pointers (including type-unsafe pointers) and interfaces. For more information on <code class="tmd-code-span">nil</code>, please read <a href="nil.html">nil in Go</a>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
There are several kinds of value representation forms in code, including <a href="basic-types-and-value-literals.html">literals</a>, <a href="constants-and-variables.html#constant">named constants</a>, <a href="constants-and-variables.html#variable">variables</a> and <a href="expressions-and-statements.html">expressions</a>, though the former three can be viewed as special cases of the latter one.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
A value can be <a href="constants-and-variables.html#untyped-value">typed or untyped</a>.
</div>
<p></p>
<div class="tmd-usual">
All kinds of basic value literals have been introduced in the article <a href="basic-types-and-value-literals.html">href="l"&gt;basic types and basic value literals</a>. There are two more kinds of literals in Go, composite literals and function literals.
</div>
<p></p>
<div class="tmd-usual">
Function literals, as the name implies, are used to represent function values. A <a href="function-declarations-and-calls.html#declaration">function declaration</a> is composed of a function literal and an identifier (the function name).
</div>
<p></p>
<div class="tmd-usual">
Composite literals are used to represent values of struct types and container types (arrays, slices and maps), Please read <a href="struct.html">structs in Go</a> and <a href="container.html">containers in Go</a> for more details.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
There are no literals to represent values of pointers, channels and interfaces.
</div>
<p></p>
<h3 id="value-part" class="tmd-header-3">
Concept: Value Parts
</h3>
<p></p>
<div class="tmd-usual">
At run time, many values are stored somewhere in memory. In Go, each of such values has a direct part. However, some of them have one or more indirect parts. Each value part occupies a continuous memory segment. The indirect underlying parts of a value are referenced by its direct part through (<a href="pointer.html">safe</a> or <a href="unsafe.html">unsafe</a>) pointers.
</div>
<p></p>
<div class="tmd-usual">
The terminology <a href="value-part.html"><span class="tmd-bold">value part</span></a> is not defined in Go specification. It is just used in Go 101 to make some explanations simpler and help Go programmers understand Go types and values better.
</div>
<p></p>
<p></p>
<h3 id="value-size" class="tmd-header-3">
Concept: Value Sizes
</h3>
<p></p>
<div class="tmd-usual">
When a value is stored in memory, the number of bytes occupied by the direct part of the value is called the size of the value. As all values of the same type have the same value size, we often simply call this the size of the type.
</div>
<p></p>
<div class="tmd-usual">
We can use the <code class="tmd-code-span">Sizeof</code> function in the <code class="tmd-code-span">unsafe</code> standard package to get the size of any value.
</div>
<p></p>
<div class="tmd-usual">
Go specification doesn't specify value size requirements for non-numeric types. The requirements for value sizes of all kinds of basic numeric types are listed in the article <a href="basic-types-and-value-literals.html">basic types and basic value literals</a>.
</div>
<p></p>
<p></p>
<h3 id="pointer-base-type" class="tmd-header-3">
Concept: Base Type of a Pointer Type
</h3>
<p></p>
<div class="tmd-usual">
For a pointer type, assume its underlying type can be denoted as <code class="tmd-code-span">*T</code> in literal, then <code class="tmd-code-span">T</code> is called the base type of the pointer type.
</div>
<p></p>
<div class="tmd-usual">
More information on pointer types and values can be found in the article <a href="pointer.html">pointers in Go</a>.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Concept: Fields of a Struct Type
</h3>
<p></p>
<div class="tmd-usual">
A struct type consists a collection of member variable declarations. Each of the member variable declarations is called a "field" of the struct type. For example, the following struct type <code class="tmd-code-span">Book</code> has three fields, <code class="tmd-code-span">author</code>, <code class="tmd-code-span">title</code> and <code class="tmd-code-span">pages</code>.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">type Book struct {
	author string
	title  string
	pages  int
}
</code></pre>
<p></p>
<div class="tmd-usual">
More information on struct types and values can be found in the article <a href="struct.html">structs in Go</a>.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Concept: Signature of Function Types
</h3>
<p></p>
<div class="tmd-usual">
The signature of a function type is composed of the input parameter definition list and the output result definition list of the function.
</div>
<p></p>
<div class="tmd-usual">
The function name and body are not parts of a function signature. Parameter and result types are important for a function signature, but parameter and result names are not important.
</div>
<p></p>
<div class="tmd-usual">
Please read <a href="function.html">functions in Go</a> for more details on function types and function values.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Concept: Methods and Method Set of a Type
</h3>
<p></p>
<div class="tmd-usual">
In Go, some types can have <a href="method.html">methods</a>. Methods can also be called member functions. The method set of a type is composed of all the methods of the type.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Concept: Dynamic Type and Dynamic Value of an Interface Value
</h3>
<p></p>
<div class="tmd-usual">
Interface values are values whose types are interface types.
</div>
<p></p>
<div class="tmd-usual">
Each interface value can box a non-interface value in it. The value boxed in an interface value is called the dynamic value of the interface value. The type of the dynamic value is called the dynamic type of the interface value. An interface value boxing nothing is a zero interface value. A zero interface value has neither a dynamic value nor a dynamic type.
</div>
<p></p>
<div class="tmd-usual">
An interface type can specify zero or several methods, which form the method set of the interface type.
</div>
<p></p>
<div class="tmd-usual">
If the method set of a type, which is either an interface type or a non-interface type, is the super set of the method set of an interface type, we say the type <a href="interface.html#implementation">implements</a> the interface type.
</div>
<p></p>
<div class="tmd-usual">
For more about interface types and values, please read <a href="interface.html">interfaces in Go</a>.
</div>
<p></p>
<p></p>
<h3 id="concrete-type" class="tmd-header-3">
Concept: Concrete Value and Concrete Type of a Value
</h3>
<p></p>
<div class="tmd-usual">
For a (typed) non-interface value, its concrete value is itself and its concrete type is the type of the value.
</div>
<p></p>
<div class="tmd-usual">
A zero interface value has neither concrete type nor concrete value. For a non-zero interface value, its concrete value is its dynamic value and its concrete type is its dynamic type.
</div>
<p></p>
<h3 class="tmd-header-3">
Concept: Container Types
</h3>
<p></p>
<div class="tmd-usual">
Arrays, slices and maps can be viewed as formal container types.
</div>
<p></p>
<div class="tmd-usual">
Sometimes, string and channel types can also be viewed as container types informally.
</div>
<p></p>
<div class="tmd-usual">
Each value of a formal or informal container type has a length.
</div>
<p></p>
<div class="tmd-usual">
More information on formal container types and values can be found in the article <a href="container.html">containers in Go</a>.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Concept: Key Type of a Map Type
</h3>
<p></p>
<div class="tmd-usual">
If the underlying type of a map type can be denoted as <code class="tmd-code-span">map[Tkey]T</code>, then <code class="tmd-code-span">Tkey</code> is called the key type of the map type. <code class="tmd-code-span">Tkey</code> must be a comparable type (see below).
</div>
<p></p>
<h3 class="tmd-header-3">
Concept: Element Type of a Container Type
</h3>
<p></p>
<div class="tmd-usual">
The types of the elements stored in values of a container type must be identical. The identical type of the elements is called the element type of the container type.
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
For an array type, if its underlying type is <code class="tmd-code-span">[N]T</code>, then its element type is <code class="tmd-code-span">T</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
For a slice type, if its underlying type is <code class="tmd-code-span">[]T</code>, then its element type is <code class="tmd-code-span">T</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
For a map type, if its underlying type is <code class="tmd-code-span">map[Tkey]T</code>, then its element type is <code class="tmd-code-span">T</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
For a channel type, if its underlying type is <code class="tmd-code-span">chan T</code>, <code class="tmd-code-span">chan&lt;- T</code> or <code class="tmd-code-span">&lt;-chan T</code>, then its element type is <code class="tmd-code-span">T</code>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
The element type of any string type is always <code class="tmd-code-span">byte</code> (a.k.a. <code class="tmd-code-span">uint8</code>).
</div>
</li>
</ul>
<p></p>
<h3 class="tmd-header-3">
Concept: Directions of Channel Types
</h3>
<p></p>
<div class="tmd-usual">
Channel values can be viewed as synchronized first-in-first-out (FIFO) queues. Channel types and values have directions.
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
A channel value which is both sendable and receivable is called a bidirectional channel. Its type is called a bidirectional channel type. The underlying types of bidirectional channel types are denoted by the <code class="tmd-code-span">chan T</code> literal.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
A channel value which is only sendable is called a send-only channel. Its type is called a send-only channel type. Send-only channel types are denoted by the <code class="tmd-code-span">chan&lt;- T</code> literal.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
A channel value which is only receivable is called a receive-only channel. Its type is called a receive-only channel type. Receive-only channel types are denoted by the <code class="tmd-code-span">&lt;-chan T</code> literal.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
More information on channel types and values can be found in the article <a href="channel.html">channels in Go</a>.
</div>
<p></p>
<p></p>
<h3 id="types-not-support-comparison" class="tmd-header-3">
Fact: Types Which Support or Don't Support Comparisons
</h3>
<p></p>
<div class="tmd-usual">
Currently (Go 1.25), Go doesn't support comparisons (with the <code class="tmd-code-span">==</code> and <code class="tmd-code-span">!=</code> operators) for values of the following types:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
slice types
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
map types
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
function types*. any struct type with a field whose type is incomparable and any array type which element type is incomparable.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
Above listed types are called incomparable types. All other types are called comparable types. Compilers forbid comparing two values of incomparable types.
</div>
<p></p>
<div class="tmd-usual">
Note, incomparable types are also called uncomparable types in many articles.
</div>
<p></p>
<div class="tmd-usual">
The key type of any map type must be a comparable type.
</div>
<p></p>
<div class="tmd-usual">
We can learn more about the detailed rules of comparisons from the article <a href="value-conversions-assignments-and-comparisons.html#comparison-rules">value conversions, assignments and comparisons in Go</a>.
</div>
<p></p>
<p></p>
<h3 class="tmd-header-3">
Fact: Object-Oriented Programming in Go
</h3>
<p></p>
<div class="tmd-usual">
Go is not a full-featured object-oriented programming language, but Go really supports some object-oriented programming elements. Please read the following listed articles for details:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="method.html">methods in Go</a>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="interface.html#implementation">implementations in Go</a>.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
<a href="type-embedding.html">type embedding in Go</a>.
</div>
</li>
</ul>
<p></p>
<h3 class="tmd-header-3">
Fact: Generics in Go
</h3>
<p></p>
<div class="tmd-usual">
Before Go 1.18, the generic functionalities in Go were limited to built-in types and functions. Since Go 1.18, custom generics has already been supported. Please read the <a href="generic.html">generics in Go</a> article for built-in generics and the <a href="https://go101.org/generics/101.html">Go Generics 101</a> book for custom generics.
</div>
<p></p>
<p></p>
</div>
